<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>中国店铺分布与互联网络</title>
  <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    body {
      background-color: #0f1736;
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      color: #fff;
      display: flex;
      flex-direction: column;
      min-height: 100vh;
      padding: 20px;
    }
    .container {
      width: 100%;
      max-width: 1200px;
      margin: 0 auto;
      background: rgba(16, 25, 52, 0.8);
      border-radius: 15px;
      padding: 25px;
      box-shadow: 0 0 30px rgba(72, 191, 255, 0.3);
      position: relative;
    }
    header {
      text-align: center;
      padding: 20px 0;
      margin-bottom: 20px;
      border-bottom: 1px solid rgba(72, 191, 255, 0.3);
    }
    h1 {
      font-size: 2.2rem;
      margin-bottom: 10px;
      background: linear-gradient(90deg, #48bfff, #ff4d6d);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
    }
    .description {
      color: #a0aec0;
      max-width: 800px;
      margin: 0 auto;
      line-height: 1.6;
    }
    #shopMap {
      width: 100%;
      height: 600px;
      border-radius: 10px;
      margin: 20px 0;
    }
    .controls {
      display: flex;
      justify-content: center;
      gap: 15px;
      margin: 20px 0;
      flex-wrap: wrap;
    }
    .btn {
      padding: 10px 20px;
      background: rgba(72, 191, 255, 0.2);
      border: 1px solid rgba(72, 191, 255, 0.5);
      color: #fff;
      border-radius: 5px;
      cursor: pointer;
      transition: all 0.3s;
      font-size: 14px;
    }
    .btn:hover {
      background: rgba(72, 191, 255, 0.3);
      transform: translateY(-2px);
    }
    .legend {
      display: flex;
      justify-content: center;
      gap: 20px;
      margin-top: 20px;
      flex-wrap: wrap;
      padding: 15px;
      background: rgba(16, 25, 52, 0.6);
      border-radius: 10px;
    }
    .legend-item {
      display: flex;
      align-items: center;
      gap: 8px;
    }
    .legend-color {
      width: 20px;
      height: 20px;
      border-radius: 50%;
    }
    .info-panel {
      background: rgba(16, 25, 52, 0.6);
      border-radius: 10px;
      padding: 15px;
      margin-top: 20px;
    }
    .info-title {
      color: #48bfff;
      margin-bottom: 10px;
      font-size: 18px;
    }
    .info-content {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 15px;
    }
    .info-card {
      background: rgba(72, 191, 255, 0.1);
      padding: 15px;
      border-radius: 8px;
    }
    .info-card h4 {
      color: #ff4d6d;
      margin-bottom: 8px;
    }
    .status {
      text-align: center;
      margin: 10px 0;
      color: #48bfff;
    }
    footer {
      text-align: center;
      margin-top: 30px;
      padding: 20px;
      color: #a0aec0;
      font-size: 0.9rem;
    }

    /* 自定义弹出窗口样式 */
    .shop-popup {
      position: absolute;
      background: rgba(16, 25, 52, 0.95);
      border: 1px solid rgba(72, 191, 255, 0.5);
      border-radius: 10px;
      padding: 15px;
      box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
      z-index: 1000;
      min-width: 250px;
      backdrop-filter: blur(10px);
      display: none;
    }
    .shop-popup h3 {
      margin: 0 0 10px;
      color: #48bfff;
      border-bottom: 1px solid rgba(72, 191, 255, 0.3);
      padding-bottom: 8px;
    }
    .shop-popup p {
      margin: 8px 0;
      display: flex;
      align-items: center;
      gap: 8px;
    }
    .shop-popup .rating {
      color: #f39c12;
    }
    .shop-popup .location {
      color: #e74c3c;
    }
    .shop-popup button {
      background: #3a6ea5;
      color: white;
      border: none;
      padding: 8px 12px;
      border-radius: 4px;
      cursor: pointer;
      width: 100%;
      margin-top: 10px;
      transition: background 0.3s;
    }
    .shop-popup button:hover {
      background: #2c5282;
    }
    .shop-popup .close-btn {
      position: absolute;
      top: 10px;
      right: 10px;
      background: none;
      border: none;
      color: #a0aec0;
      font-size: 16px;
      cursor: pointer;
      width: auto;
    }

    @media (max-width: 768px) {
      h1 {
        font-size: 1.8rem;
      }
      #shopMap {
        height: 400px;
      }
      .controls {
        flex-direction: column;
        align-items: center;
      }
      .btn {
        width: 200px;
      }
    }
  </style>
</head>
<body>
<div class="container">
  <header>
    <h1>中国店铺分布与互联网络</h1>
    <p class="description">可视化展示全国主要城市的店铺分布情况以及城市间的业务联系，通过连线粗细和颜色表示业务量大小</p>
  </header>

  <div class="status" id="status">正在加载地图数据...</div>
  <div id="shopMap"></div>

  <div class="controls">
    <button class="btn" id="resetView">重置视图</button>
    <button class="btn" id="toggleRotation">开启自动旋转</button>
    <button class="btn" id="zoomIn">放大</button>
    <button class="btn" id="zoomOut">缩小</button>
    <select class="btn" id="mapFilter">
      <option value="all">所有店铺</option>
      <option value="4.5">评分4.5以上</option>
      <option value="4.0">评分4.0以上</option>
    </select>
  </div>

  <div class="legend">
    <div class="legend-item">
      <div class="legend-color" style="background-color: #ff4d6d;"></div>
      <span>店铺密集 (80+家)</span>
    </div>
    <div class="legend-item">
      <div class="legend-color" style="background-color: #48bfff;"></div>
      <span>店铺中等 (50-79家)</span>
    </div>
    <div class="legend-item">
      <div class="legend-color" style="background-color: #7209b7;"></div>
      <span>店铺较少 (<50家)</span>
    </div>
  </div>

  <div class="info-panel">
    <h3 class="info-title">数据统计</h3>
    <div class="info-content">
      <div class="info-card">
        <h4>店铺总数</h4>
        <p>1,248 家</p>
      </div>
      <div class="info-card">
        <h4>覆盖城市</h4>
        <p>28 个城市</p>
      </div>
      <div class="info-card">
        <h4>月业务量</h4>
        <p>12,584 单</p>
      </div>
      <div class="info-card">
        <h4>同比增长</h4>
        <p>+18.3%</p>
      </div>
    </div>
  </div>
</div>

<!-- 自定义弹出窗口 -->
<div class="shop-popup" id="shopPopup">
  <button class="close-btn" id="closePopup"><i class="fas fa-times"></i></button>
  <h3 id="popupTitle">店铺名称</h3>
  <p><i class="fas fa-star rating"></i> 评分: <span id="popupRating">0</span>/5.0</p>
  <p><i class="fas fa-map-marker-alt location"></i> 位置: <span id="popupLocation">未知</span></p>
  <p><i class="fas fa-store"></i> 类型: <span id="popupType">未知</span></p>
  <button id="viewDetails">查看详情</button>
</div>

<footer>
  <p>© 2023 巷陌后台管理系统 | 数据可视化平台 | 技术支持: ECharts 5.4.3</p>
</footer>

<script>
  // 初始化地图函数
  function initEchartsChinaMap() {
    // 1. 获取地图容器并初始化ECharts实例
    const chartDom = document.getElementById("shopMap");
    const myChart = echarts.init(chartDom);
    const statusElement = document.getElementById("status");
    const popup = document.getElementById("shopPopup");
    const closePopupBtn = document.getElementById("closePopup");

    // 2. 定义城市坐标
    const cityGeo = {
      北京: [116.4042, 39.9153],
      上海: [121.4737, 31.2304],
      广州: [113.2806, 23.1251],
      深圳: [114.0579, 22.5431],
      成都: [104.0665, 30.5728],
      西安: [108.9466, 34.2647],
      杭州: [120.1551, 30.2741],
      武汉: [114.3055, 30.5928],
      南京: [118.7969, 32.0603],
      重庆: [106.5516, 29.5630],
      天津: [117.1901, 39.1256],
      苏州: [120.5853, 31.2990]
    };

    // 3. 自定义店铺数据
    const shopsData = [
      { name: "巷角咖啡", city: "北京", rating: 4.8, type: "餐饮" },
      { name: "老街书屋", city: "北京", rating: 4.7, type: "文化" },
      { name: "时光杂货铺", city: "上海", rating: 4.6, type: "零售" },
      { name: "深夜食堂", city: "上海", rating: 4.5, type: "餐饮" },
      { name: "花间茶室", city: "广州", rating: 4.5, type: "餐饮" },
      { name: "城市之光书店", city: "广州", rating: 4.4, type: "文化" },
      { name: "小确幸花店", city: "深圳", rating: 4.3, type: "零售" },
      { name: "匠人手工坊", city: "深圳", rating: 4.7, type: "文化" },
      { name: "川味小馆", city: "成都", rating: 4.9, type: "餐饮" },
      { name: "蜀绣工坊", city: "成都", rating: 4.6, type: "文化" },
      { name: "杭帮菜馆", city: "杭州", rating: 4.5, type: "餐饮" },
      { name: "西湖茶社", city: "杭州", rating: 4.8, type: "餐饮" }
    ];

    // 4. 构造连线数据
    const linesData = [
      { from: "北京", to: "上海", value: 120 },
      { from: "广州", to: "深圳", value: 90 },
      { from: "成都", to: "西安", value: 75 },
      { from: "杭州", to: "武汉", value: 88 },
      { from: "北京", to: "广州", value: 150 },
      { from: "上海", to: "杭州", value: 60 },
      { from: "南京", to: "苏州", value: 45 },
      { from: "重庆", to: "成都", value: 78 },
      { from: "天津", to: "北京", value: 65 }
    ];

    // 转换为ECharts需要的格式
    const linesFormatted = linesData.map(item => ({
      fromName: item.from,
      toName: item.to,
      coords: [cityGeo[item.from], cityGeo[item.to]],
      value: item.value
    }));

    // 5. 构造城市标记数据
    const scatterData = Object.keys(cityGeo).map(city => {
      const cityShops = shopsData.filter(shop => shop.city === city);
      const shopCount = cityShops.length;
      return {
        name: city,
        value: [cityGeo[city][0], cityGeo[city][1], shopCount],
        shopCount: shopCount,
        itemStyle: {
          color: shopCount > 5 ? "#ff4d6d" : shopCount > 2 ? "#48bfff" : "#7209b7"
        }
      };
    });

    // 6. 构造店铺标记数据
    const shopPoints = shopsData.map(shop => {
      // 在城市坐标基础上添加一些随机偏移，避免完全重叠
      const baseCoord = cityGeo[shop.city];
      const offsetX = (Math.random() - 0.5) * 0.5;
      const offsetY = (Math.random() - 0.5) * 0.5;

      return {
        name: shop.name,
        value: [baseCoord[0] + offsetX, baseCoord[1] + offsetY],
        city: shop.city,
        rating: shop.rating,
        type: shop.type,
        symbolSize: 12,
        itemStyle: {
          color: shop.rating >= 4.5 ? "#ff4d6d" : shop.rating >= 4.0 ? "#48bfff" : "#7209b7"
        }
      };
    });

    // 7. 显示加载状态
    statusElement.textContent = "正在加载地图数据...";

    // 8. 加载中国地图数据
    fetch('https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json')
            .then(response => {
              if (!response.ok) {
                throw new Error('地图数据加载失败');
              }
              return response.json();
            })
            .then(chinaJson => {
              // 注册地图
              echarts.registerMap('china', chinaJson);

              // 更新状态
              statusElement.textContent = "地图数据加载成功！";
              setTimeout(() => {
                statusElement.style.display = "none";
              }, 2000);

              // 设置ECharts配置项
              const option = {
                backgroundColor: "#0f1736",
                title: {
                  text: "中国店铺分布与互联网络",
                  left: "center",
                  textStyle: { color: "#fff", fontSize: 18, fontWeight: "bold" }
                },
                tooltip: {
                  trigger: "item",
                  formatter: function(params) {
                    if (params.seriesType === "scatter") {
                      if (params.seriesId === "shops") {
                        // 店铺点提示
                        return `<div style="padding: 8px;">
                            <h4 style="margin:0; color:#48bfff;">${params.data.name}</h4>
                            <p>城市：${params.data.city}</p>
                            <p>评分：${params.data.rating} <i class="fas fa-star" style="color: #f39c12;"></i></p>
                            <p>类型：${params.data.type}</p>
                          </div>`;
                      } else {
                        // 城市点提示
                        const shopCount = params.data.shopCount || params.data.value[2] || 0;
                        return `<div style="padding: 8px;">
                            <h4 style="margin:0; color:#48bfff;">${params.name}</h4>
                            <p>店铺数量：${shopCount}家</p>
                          </div>`;
                      }
                    } else if (params.seriesType === "lines") {
                      return `<div style="padding: 8px;">
                          <p>连接：${params.data.fromName} → ${params.data.toName}</p>
                          <p>业务量：${params.data.value}</p>
                        </div>`;
                    }
                    return params.name;
                  }
                },
                visualMap: {
                  show: true,
                  type: "piecewise",
                  pieces: [
                    { min: 80, color: "#ff4d6d" },
                    { min: 50, max: 79, color: "#48bfff" },
                    { max: 49, color: "#7209b7" }
                  ],
                  left: "left",
                  top: "bottom",
                  textStyle: { color: "#fff" }
                },
                geo: {
                  map: "china",
                  roam: true,
                  center: [105.0, 36.0],
                  zoom: 1.2,
                  label: {
                    show: true,
                    color: "#fff",
                    fontSize: 10
                  },
                  emphasis: {
                    label: { color: "#fff", fontSize: 12 },
                    itemStyle: { areaColor: "#48bfff", borderColor: "#fff" }
                  },
                  itemStyle: {
                    areaColor: "rgba(72, 191, 255, 0.1)",
                    borderColor: "rgba(72, 191, 255, 0.3)",
                    borderWidth: 1
                  }
                },
                series: [
                  // 系列1：炫酷连线（流光效果）
                  {
                    name: "城市连线",
                    type: "lines",
                    coordinateSystem: "geo",
                    zlevel: 2,
                    effect: {
                      show: true,
                      period: 4,
                      trailLength: 0.6,
                      color: "#ff4d6d",
                      symbolSize: 6
                    },
                    lineStyle: {
                      color: function(params) {
                        const value = params.data.value;
                        return value > 100 ? "#ff4d6d" : value > 80 ? "#48bfff" : "#7209b7";
                      },
                      width: 2,
                      opacity: 0.8,
                      curveness: 0.2
                    },
                    data: linesFormatted
                  },
                  // 系列2：城市标记（散点）
                  // {
                  //   name: "城市分布",
                  //   type: "scatter",
                  //   coordinateSystem: "geo",
                  //   zlevel: 3,
                  //   symbol: "circle",
                  //   symbolSize: function(params) {
                  //     const shopCount = params.data.shopCount || params.data.value[2] || 0;
                  //     return Math.min(shopCount * 3 + 10, 30);
                  //   },
                  //   itemStyle: {
                  //     color: function(params) {
                  //       const shopCount = params.data.shopCount || params.data.value[2] || 0;
                  //       return shopCount > 5 ? "#ff4d6d" : shopCount > 2 ? "#48bfff" : "#7209b7";
                  //     }
                  //   },
                  //   data: scatterData,
                  //   label: {
                  //     show: true,
                  //     position: 'top',
                  //     formatter: function(params) {
                  //       return params.data.name;
                  //     },
                  //     color: '#fff',
                  //     fontSize: 10,
                  //     backgroundColor: 'rgba(0,0,0,0.7)',
                  //     padding: [3, 5],
                  //     borderRadius: 4
                  //   }
                  // },
                  // 系列3：店铺标记（散点）
                  {
                    id: "shops",
                    name: "店铺分布",
                    type: "scatter",
                    coordinateSystem: "geo",
                    zlevel: 4,
                    symbol: "pin",
                    symbolSize: 40,
                    data: shopPoints,
                    label: {
                      show: false
                    },
                    emphasis: {
                      itemStyle: {
                        shadowBlur: 10,
                        shadowColor: 'rgba(255, 255, 255, 0.8)'
                      }
                    }
                  }
                ]
              };

              // 9. 渲染地图
              myChart.setOption(option);

              // 10. 添加点击事件处理
              myChart.on('click', function(params) {
                if (params.seriesId === "shops") {
                  // 显示店铺详情弹窗
                  showShopPopup(params.data, params.event.event);
                }
              });

              // 11. 添加控制功能
              setupControls(myChart);
            })
            .catch(error => {
              console.error('加载地图数据失败:', error);
              statusElement.textContent = "地图数据加载失败，请刷新页面重试";
              statusElement.style.color = "#ff4d6d";
            });

    // 显示店铺详情弹窗
    function showShopPopup(shopData, event) {
      const popup = document.getElementById("shopPopup");
      document.getElementById("popupTitle").textContent = shopData.name;
      document.getElementById("popupRating").textContent = shopData.rating;
      document.getElementById("popupLocation").textContent = shopData.city;
      document.getElementById("popupType").textContent = shopData.type;

      // 设置弹窗位置
      popup.style.left = (event.clientX + 10) + 'px';
      popup.style.top = (event.clientY + 10) + 'px';
      popup.style.display = 'block';
    }

    // 关闭弹窗
    closePopupBtn.addEventListener('click', function() {
      popup.style.display = 'none';
    });

    // 点击查看详情按钮
    document.getElementById("viewDetails").addEventListener('click', function() {
      const shopName = document.getElementById("popupTitle").textContent;
      alert(`查看 ${shopName} 的详细信息`);
      // 这里可以跳转到详情页或打开模态框显示更多信息
    });

    // 筛选功能
    document.getElementById('mapFilter').addEventListener('change', function(e) {
      const minRating = parseFloat(e.target.value);
      let filteredShops;

      if (minRating === 0) {
        filteredShops = shopPoints;
      } else {
        filteredShops = shopPoints.filter(shop => shop.rating >= minRating);
      }

      myChart.setOption({
        series: [{
          id: "shops",
          data: filteredShops
        }]
      });
    });

    // 设置控制功能
    function setupControls(myChart) {
      let rotationInterval = null;

      document.getElementById('resetView').addEventListener('click', function() {
        myChart.setOption({
          geo: {
            center: [105.0, 36.0],
            zoom: 1.2,
            rotation: 0
          }
        });
      });

      document.getElementById('toggleRotation').addEventListener('click', function() {
        if (rotationInterval) {
          clearInterval(rotationInterval);
          rotationInterval = null;
          this.textContent = '开启自动旋转';
        } else {
          let rotateAngle = 0;
          rotationInterval = setInterval(() => {
            rotateAngle += 0.5;
            myChart.setOption({
              geo: {
                rotation: [rotateAngle, 0, 0]
              }
            });
          }, 100);
          this.textContent = '停止自动旋转';
        }
      });

      document.getElementById('zoomIn').addEventListener('click', function() {
        const currentOption = myChart.getOption();
        const currentZoom = currentOption.geo ? currentOption.geo[0].zoom || 1.2 : 1.2;
        myChart.setOption({
          geo: {
            zoom: currentZoom * 1.2
          }
        });
      });

      document.getElementById('zoomOut').addEventListener('click', function() {
        const currentOption = myChart.getOption();
        const currentZoom = currentOption.geo ? currentOption.geo[0].zoom || 1.2 : 1.2;
        myChart.setOption({
          geo: {
            zoom: currentZoom * 0.8
          }
        });
      });

      // 窗口调整大小时重绘图表
      window.addEventListener("resize", function() {
        myChart.resize();
      });
    }
  }

  // 页面加载完成后初始化地图
  document.addEventListener('DOMContentLoaded', initEchartsChinaMap);
</script>
</body>
</html>